#ifndef TERRAIN_GEN_HXX_
#define TERRAIN_GEN_HXX_

#include "../GameObjects/MapNode.hxx"

#include <map>
#include <vector>

struct BiomeData
{
  std::vector<std::string> terrain;            ///< Terrain IDs
  std::vector<std::string> water;              ///< Water IDs
  std::vector<std::string> waterDecoration;    ///< Water Decoration IDs
  std::vector<std::string> waterFloraLight;    ///< Water Flora Light IDs
  std::vector<std::string> waterFloraMedium;   ///< Water Flora Medium IDs
  std::vector<std::string> waterFloraDense;    ///< Water Flora Dense IDs
  std::vector<std::string> terrainRocks;       ///< Terrain Rocks IDs
  std::vector<std::string> terrainDecoration;  ///< Terrain Decoration IDs
  std::vector<std::string> terrainFloraLight;  ///< Terrain Flora (Flowers) Light IDs
  std::vector<std::string> terrainFloraMedium; ///< Terrain Flora (Flowers) Medium IDs
  std::vector<std::string> terrainFloraDense;  ///< Terrain Flora (Flowers) Dense IDs
  std::vector<std::string> bushesLight;        ///< Bushes Light IDs
  std::vector<std::string> bushesMedium;       ///< Bushes Medium IDs
  std::vector<std::string> bushesDense;        ///< Bushes Dense IDs
  std::vector<std::string> treesLight;         ///< Trees Light IDs
  std::vector<std::string> treesMedium;        ///< Trees Medium IDs
  std::vector<std::string> treesDense;         ///< Trees Dense IDs
};

struct TerrainSettings
{
  int mapSize = 128;
  int seed = 0;         ///< If the seed is 0, a random seed will be generated by TerrainGenerator::generateTerrain()
  int seaLevel = 3;     ///< All tiles with elevation below this will be set as water.
  int maxHeight = 32;
  int treeDensity = 50; ///< 0% no trees, 100% All trees everywhere all the time.
  int mountainAmplitude =
      10;              ///< Both amplifies the mountain noise source, as well as biasing the mountain/plains blend. Expects 0-100.
  int waterAmount = 5; ///< Density of freshwater in addition to coastlines and rivers. Expects 0-100.
  int coasts =
      1; ///< 4 least significant bits are bitmasked, where 0 is a land border and 1 is a coastline. Remaining bits reserved for future use.
  int rivers = 1;              ///< Number of rivers to attempt generating.
  std::string biomes = "{}";   ///< JSON string of biomes to attempt using, plus any options associated with them.
  std::string advanced = "{}"; ///< JSON string of arbitrary advanced option data for future use or mods.
};

class TerrainGenerator
{
public:
  TerrainGenerator() = default;
  ~TerrainGenerator() = default;

  void generateTerrain(std::vector<MapNode> &mapNodes, std::vector<MapNode *> &mapNodesInDrawingOrder);
  void generateRiver(std::vector<MapNode> &mapNodes);

  void loadTerrainDataFromJSON();

private:
  TerrainSettings m_terrainSettings;

  std::map<std::string, BiomeData> m_biomeInformation; ///< key: biome
  std::vector<Point> m_riverSourceNodes;
};

#endif
